package com.unswift.cloud.listener;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Timer;
import java.util.TimerTask;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import com.unswift.cache.MemoryCache;
import com.unswift.cloud.adapter.logger.LoggerTimerRecordAdapter;
import com.unswift.cloud.adapter.system.timer.SystemTimerAdapter;
import com.unswift.cloud.cache.CacheEnum;
import com.unswift.cloud.core.CommonOperator;
import com.unswift.cloud.pojo.cho.system.timer.SystemTimerCho;
import com.unswift.cloud.pojo.dao.logger.timer.record.LoggerTimerRecordInsertDo;
import com.unswift.cloud.pojo.dao.system.timer.SystemTimerDataDo;
import com.unswift.cloud.pojo.dao.system.timer.SystemTimerPageDo;
import com.unswift.cloud.pojo.po.system.SystemTimer;
import com.unswift.cloud.timer.CloudTimerTask;
import com.unswift.cloud.utils.BeanUtils;
import com.unswift.utils.ClassUtils;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.ObjectUtils;
import com.unswift.utils.ThreadUtils;

@Component
@Api(value="定時器启动监听", author="unswift", date="2023-05-04", version="1.0.0")
public class TimerListener extends CommonOperator implements CommandLineRunner{

	@ApiField("日志对象")
	private final Logger logger=LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	@ApiField("系统定时器公共操作类")
	private SystemTimerAdapter systemTimerManager;
	
	@Autowired
	@ApiField("内存缓存类")
	private MemoryCache memoryCache;
	
	@Autowired
	@ApiField("定时器执行记录公共操作类")
	private LoggerTimerRecordAdapter loggerTimerRecordAdapter;
	
	@Override
	@ApiMethod(value="启动时执行的方法", params=@ApiField("启动参数"))
	public void run(String... args) throws Exception {
		ThreadUtils.execute(new Runnable() {
			@Override
			public void run() {
				startTimer();
			}
		});
	}
	
	@ApiMethod(value="管控定时器的定时器启动，监听定时器的改动，在服务器启动60秒后执行，每60秒刷新一次")
	private void startTimer(){
		Timer timer=new Timer("server-timer");
		timer.schedule(new TimerTask() {
			@Override
			public void run() {
				handerTimer();
			}
		}, 60*1000, 60*1000);
	}
	
	@ApiMethod(value="根据定时器配置启动客户定时器")
	private void handerTimer(){
		SystemTimerPageDo search = new SystemTimerPageDo();
		List<SystemTimerDataDo> timerList = systemTimerManager.findList(search);
		List<SystemTimerCho> cacheTimerList=memoryCache.get(CacheEnum.SYSTEM_TIMER_DATA_LIST.getKey());
		Map<String, SystemTimerCho> cacheTimerMap=new HashMap<String, SystemTimerCho>();
		if(ObjectUtils.isNotEmpty(cacheTimerList)){
			cacheTimerMap=cacheTimerList.stream().collect(Collectors.toMap(SystemTimerCho::getTimerKey, t -> t));
		}
		if(ObjectUtils.isNotEmpty(timerList)){
			SystemTimerCho cacheTimer;
			memoryCache.setList(CacheEnum.SYSTEM_TIMER_DATA_LIST.getKey(), this.convertPojoList(timerList, SystemTimerCho.class));
			for (SystemTimer timer : timerList) {
				cacheTimer=cacheTimerMap.get(timer.getTimerKey());
				if(ObjectUtils.isEmpty(cacheTimer)){
					loadingTimer(timer);
					continue;
				}
				if(!timer.getRunningCycle().equals(cacheTimer.getRunningCycle()) || 
						!timer.getRunningType().equals(cacheTimer.getRunningType()) || 
						!timer.getExecuteBean().equals(cacheTimer.getExecuteBean())){
					Timer running=memoryCache.getHash(CacheEnum.SYSTEM_TIMER_MAP.getKey(), timer.getTimerKey());
					running.cancel();//停止定时器
					createTimerRecord(timer.getId(), "end", (byte)1, "定时器结束");
					memoryCache.removeHash(CacheEnum.SYSTEM_TIMER_MAP.getKey(), timer.getTimerKey());
					loadingTimer(timer);
				}
				cacheTimerMap.remove(timer.getTimerKey());
			}
		}
		if(ObjectUtils.isNotEmpty(cacheTimerMap)){
			for (Entry<String, SystemTimerCho> timerEntry : cacheTimerMap.entrySet()) {
				Timer running=memoryCache.getHash(CacheEnum.SYSTEM_TIMER_MAP.getKey(), timerEntry.getKey());
				running.cancel();//停止定时器
				createTimerRecord(timerEntry.getValue().getId(), "end", (byte)1, "定时器结束");
				memoryCache.removeHash(CacheEnum.SYSTEM_TIMER_MAP.getKey(), timerEntry.getKey());
			}
		}
	}
	
	private void loadingTimer(SystemTimer timer){
		Timer timerRunning=new Timer(timer.getTimerKey());
		CloudTimerTask executeBean = BeanUtils.getBean(ClassUtils.forName(timer.getExecuteBean()));
		if("delay".equals(timer.getRunningType())){
			long cycle=ObjectUtils.evalJs(timer.getRunningCycle(), long.class);
			timerRunning.schedule(new TimerTask() {
				@Override
				public void run() {
					try {
						executeBean.run();
						createTimerRecord(timer.getId(), "running", (byte)1, "执行成功");
					} catch (Exception e) {
						e.printStackTrace();
						logger.error(e.getMessage(), e);
						createTimerRecord(timer.getId(), "running", (byte)0, ExceptionUtils.getStackTrace(e));
					}
				}
			}, 0, cycle);
		}
		createTimerRecord(timer.getId(), "start", (byte)1, "定时器启动");
		memoryCache.setHash(CacheEnum.SYSTEM_TIMER_MAP.getKey(), timer.getTimerKey(), timerRunning);
	}
	
	private void createTimerRecord(long timerId, String type, byte result, String message){
		LoggerTimerRecordInsertDo record=new LoggerTimerRecordInsertDo();
		record.setTimerId(timerId);
		record.setType(type);
		record.setResult(result);
		record.setMessage(message);
		loggerTimerRecordAdapter.save(record, false);
	}
}
